import java.io.BufferedReader;

import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.Type;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import org.java_websocket.*;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_17;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;


public class SocketServerDemo3 {

	private static int serverPort = 9999;
	private static ServerSocket serverSocket;

	// 用串列來儲存每個client
	private static ArrayList<Socket> players = new ArrayList<Socket>();

	// 程式進入點
	public static void main(String[] args) {
		try {
			
			serverSocket = new ServerSocket(serverPort);
			System.out.println("Server is start.");

			// 當Server運作中時
			while (!serverSocket.isClosed()) {
				// 顯示等待客戶端連接
				System.out.println("Wait new clinet connect");

				// 呼叫等待接受客戶端連接
				waitNewPlayer();
			}
	
		} catch (IOException e) {
			System.out.println("Server Socket ERROR");
		}

	}

	// 等待接受客戶端連接
	public static void waitNewPlayer() {
		try {
			

			Socket socket = serverSocket.accept();
			//呼叫創造新的使用者
			createNewPlayer(socket);
		} catch (IOException e)  {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	// 創造新的使用者
	public static void createNewPlayer(final Socket socket) {

		// 以新的執行緒來執行
		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					// 增加新的使用者
					players.add(socket);

					// 取得網路串流		
					/*
					BufferedReader br = new BufferedReader( new
							 InputStreamReader(socket.getInputStream()));

					while(!br.readLine().isEmpty()){
						System.out.println(br.readLine());
					}
					*/
					//使用Json Reader來讀取串流
					
					JsonReader reader = new JsonReader(new InputStreamReader(
							socket.getInputStream(), "UTF-8"));
					
					//用來讀取網頁傳過來的完整資訊
					
					DataInputStream in = new DataInputStream(socket.getInputStream());
					byte[] b = new byte[in.available()];
					in.readFully(b);
					System.out.println(new String(b));
					
					
					// 當Socket已連接時連續執行
					while (socket.isConnected()) {
						
						// 取得網路串流的訊息
						// String msg = br.readLine();
						// System.out.println(msg);

						// 收到空字串時判定為斷線
						/*
						 * if (msg == null) break;
						 */
						// 廣播訊息給其它的客戶端,串流方式
						// castMsg(msg);
						// JSON格式的字串，要重新編譯後廣播出去,Json格式
						// jsonMsg(msg);

						//Json Reader格式
						
						if (reader == null){ 
							break;
						}
						jsonMsg(readMessage(reader));
						
						// 移除客戶端
						players.remove(socket);
						
					}
				} catch (IOException e) {

				}

			}
		});

		// 啟動執行緒
		t.start();
	}

	public static Message readMessage(JsonReader reader) throws IOException {
		//
		String name = null;
		String msg = null;
		String time = null;
		//開始讀取Json元素
		reader.beginObject();
		//觀看Json裡的資料
		while (reader.hasNext()) {
			String type = reader.nextName();
			if (type.equals("name")) {
				name = reader.nextString();
			} else if (type.equals("msg")) {
				msg = reader.nextString();
			} else if (type.equals("time")) {
				time = reader.nextString();
			} else {
				reader.skipValue();
			}
		}
		reader.endObject();
		//回傳一個新的message聊天物件,
		return new Message(name, msg, time);
	}

	//接收到Message的物件，開始傳送資訊出去
	public static void jsonMsg(Message message) {
		// 創造socket陣列
		Socket[] ps = new Socket[players.size()];
		players.toArray(ps);

		// 走訪ps中的每一個元素
		for (Socket socket : ps) {
			try {
				// 創造網路輸出串流
				BufferedWriter bw;
				bw = new BufferedWriter(new OutputStreamWriter(
						socket.getOutputStream()));

				// 寫入訊息到串流
				bw.write(message.getName() + ":" + message.getMsg() + "\t\t"
						+ message.getTime() + "\n");
				// 立即發送
				bw.flush();

				System.out.println(message.getName() + ":" + message.getMsg()
						+ "\t\t" + message.getTime());


			} catch (IOException e) {

			}
		}
	}

	// 這邊修改內容成我們需要的內容
	public static void jsonMsg(String Msg) {
		// 創造socket陣列
		Socket[] ps = new Socket[players.size()];

		// 將players轉換成陣列存入ps
		players.toArray(ps);

		// 走訪ps中的每一個元素
		for (Socket socket : ps) {
			try {
				// 創造網路輸出串流
				BufferedWriter bw;
				bw = new BufferedWriter(new OutputStreamWriter(
						socket.getOutputStream()));

				Gson gson = new Gson();
				Message message = gson.fromJson(Msg, Message.class);

				// 寫入訊息到串流
				bw.write(message.getName() + ":" + message.getMsg() + "\t\t"
						+ message.getTime() + "\n");
				// 立即發送
				bw.flush();
				System.out.println(message.getName() + ":" + message.getMsg()
						+ "\t\t" + message.getTime() + "-" + ps.length + "人");

				// String json = gson.toJson(message);
				// System.out.println(json);
				// System.out.println("目前人數"+(players.size())+"人");

			} catch (IOException e) {

			}
		}
	}

	// 廣播訊息給其它的客戶端
	public static void castMsg(String Msg) {
		// 創造socket陣列
		Socket[] ps = new Socket[players.size()];
		// 將players轉換成陣列存入ps
		players.toArray(ps);
		// 走訪ps中的每一個元素
		for (Socket socket : ps) {
			try {
				// 創造網路輸出串流
				BufferedWriter bw;
				bw = new BufferedWriter(new OutputStreamWriter(
						socket.getOutputStream()));
				// 寫入訊息到串流
				bw.write(Msg + "\n" + ps.length + "\n");
				// 立即發送
				bw.flush();
			} catch (IOException e) {

			}
		}
	}


}
